-- action_system.lua
-- 修复卡顿和模式切换问题，添加翻滚功能 - 修改翻滚参数

local ActionSystem = {}
ActionSystem.__index = ActionSystem

function ActionSystem.new(characterMonitor, movementSystem)
    local instance = setmetatable({
        characterMonitor = characterMonitor,
        movementSystem = movementSystem,
        combatSystem = nil,
        
        spineNode = nil,
        currentAnimation = "idle",
        currentMode = "chi",
        
        spinePath = "model/que/que",
        scale = 0.2,
        animationSpeed = 1.0,
        recoveryTime = 0.05,
        
        animationMap = {
            chi_idle = "chi/chi-idle",
            chi_walk = "chi/chi-walk",
            chi_run = "chi/chi-run",
            chi_jump = "chi/chi-jump",
            chi_fall = "chi/chi-fall",
            chi_hurt = "chi/chi-hurt",
            chi_attack_1 = "chi/chi-a1",
            chi_attack_2 = "chi/chi-a2",
            chi_attack_3 = "chi/chi-a3",
            chi_attack_4 = "chi/chi-a4",
            
            chui_idle = "chui/chui-idle",
            chui_walk = "chui/chui-walk",
            chui_run = "chui/chui-run",
            chui_jump = "chui/chui-jump",
            chui_fall = "chui/chui-fall",
            chui_hurt = "chui/chui-hurt",
            chui_attack_1 = "chui/chui-a1",
            chui_attack_2 = "chui/chui-a2",
            chui_attack_3 = "chui/chui-a3",
            
            zao_idle = "zao/zao-idle",
            zao_walk = "zao/zao-walk",
            zao_run = "zao/zao-run",
            zao_jump = "zao/zao-jump",
            zao_fall = "zao/zao-fall",
            zao_hurt = "zao/zao-hurt",
            zao_attack_1 = "zao/zao-a1",
            zao_attack_2 = "zao/zao-a2",
            
            chi_roll = "fangun",
            chui_roll = "fangun",
            zao_roll = "fangun",
            roll = "fangun"
        },
        
        _animationDurations = {
            ["chi/chi-idle"] = 1.0,
            ["chi/chi-walk"] = 1.0,
            ["chi/chi-run"] = 1.0,
            ["chi/chi-jump"] = 0.8,
            ["chi/chi-fall"] = 0.8,
            ["chi/chi-hurt"] = 0.5,
            ["chi/chi-a1"] = 0.8,
            ["chi/chi-a2"] = 0.8,
            ["chi/chi-a3"] = 0.8,
            ["chi/chi-a4"] = 1.0,
            
            ["chui/chui-idle"] = 1.0,
            ["chui/chui-walk"] = 1.0,
            ["chui/chui-run"] = 1.0,
            ["chui/chui-jump"] = 0.8,
            ["chui/chui-fall"] = 0.8,
            ["chui/chui-hurt"] = 0.5,
            ["chui/chui-a1"] = 1.0,
            ["chui/chui-a2"] = 1.0,
            ["chui/chui-a3"] = 1.2,
            
            ["zao/zao-idle"] = 1.0,
            ["zao/zao-walk"] = 1.0,
            ["zao/zao-run"] = 1.0,
            ["zao/zao-jump"] = 0.8,
            ["zao/zao-fall"] = 0.8,
            ["zao/zao-hurt"] = 0.5,
            ["zao/zao-a1"] = 0.7,
            ["zao/zao-a2"] = 0.9,
            
            ["fangun"] = 0.4  -- 缩短翻滚动画时长到0.4秒
        },
        
        isAttackAnimation = false,
        currentAttackCombo = 0,
        
        _comboWindowStart = 0.3,
        _comboWindowEnd = 0.6,
        _inComboWindow = false,
        _comboInputLocked = true,
        _attackTimer = 0,
        
        _nextAttackQueued = false,
        _queuedComboNumber = 0,
        
        _isRolling = false,
        _rollAnimationTimer = 0,
        _rollAnimationDuration = 0.4,  -- 缩短翻滚时长
        _rollCooldown = 0,
        _rollCooldownTime = 0.1,
        _rollQueue = false,
        _lastShiftPressed = false,
        _rollStartDirection = 1,  -- 记录翻滚开始时的方向
        
        debugMode = true,
        
        _currentAttackAnimName = nil,
        _animationTimer = 0,
        _animationDuration = 0.8,
        
        _animationListenerRegistered = false,
        
        _isInitialized = false,
        
        _lastQPressed = false,
        _modeSwitchCooldown = 0,
        _modeSwitchCooldownTime = 0.3
    }, ActionSystem)
    
    return instance
end

-- 设置战斗系统引用
function ActionSystem:setCombatSystem(combatSystem)
    self.combatSystem = combatSystem
    if self.debugMode then
        print("设置战斗系统引用")
    end
end

-- 创建Spine节点
function ActionSystem:createSpineNode()
    local Spine = nil
    local success, spineModule = pcall(require, "Spine")
    if not success then
        print("错误：无法加载Spine模块")
        return nil
    end
    
    Spine = spineModule
    
    local spineNode = Spine(self.spinePath)
    
    if spineNode then
        print("✓ Spine节点创建成功")
        
        spineNode.scaleX = self.scale
        spineNode.scaleY = self.scale
        spineNode.recovery = self.recoveryTime
        spineNode.speed = self.animationSpeed
        spineNode.fliped = true
        
        return spineNode
    else
        print("✗ 创建Spine节点失败")
        return nil
    end
end

-- 设置Spine节点
function ActionSystem:setSpineNode(node)
    if not node then 
        print("错误：Spine节点为空")
        return false 
    end
    
    self.spineNode = node
    
    self:_registerAnimationListener()
    
    self:playAnimation("idle", true)
    
    self._isInitialized = true
    print("✓ Spine动画节点设置成功")
    return true
end

-- 注册动画结束事件监听器
function ActionSystem:_registerAnimationListener()
    if not self.spineNode then return end
    
    if self._animationListenerRegistered then
        self.spineNode["AnimationEnd"] = nil
        self._animationListenerRegistered = false
    end
    
    self.spineNode["AnimationEnd"] = function(animationName, target)
        self:onAnimationEnd(animationName, target)
    end
    
    self._animationListenerRegistered = true
    if self.debugMode then
        print("注册AnimationEnd事件监听器")
    end
end

-- 动画结束事件处理
function ActionSystem:onAnimationEnd(animationName, target)
    if self.debugMode then
        print("AnimationEnd事件: " .. tostring(animationName))
        print("当前攻击动画: " .. tostring(self.isAttackAnimation))
        print("当前连击: " .. self.currentAttackCombo)
        print("排队攻击: " .. tostring(self._nextAttackQueued))
        print("排队连击: " .. self._queuedComboNumber)
        print("翻滚中: " .. tostring(self._isRolling))
    end
    
    if self._isRolling and animationName == "fangun" then
        self:_handleRollAnimationEnd()
        return
    end
    
    if self.isAttackAnimation and animationName == self._currentAttackAnimName then
        local nextAttackQueued = self._nextAttackQueued
        local queuedComboNumber = self._queuedComboNumber
        
        if self.debugMode then
            print("攻击动画结束，检查排队攻击: " .. tostring(nextAttackQueued))
            if nextAttackQueued then
                print("排队连击数: " .. queuedComboNumber)
            end
        end
        
        self._inComboWindow = false
        self._comboInputLocked = true
        self._attackTimer = 0
        self._animationTimer = 0
        self._currentAttackAnimName = nil
        
        if nextAttackQueued and queuedComboNumber > 0 then
            local queuedCombo = queuedComboNumber
            
            if self.debugMode then
                print("执行排队攻击: 第 " .. queuedCombo .. " 段")
            end
            
            self._nextAttackQueued = false
            self._queuedComboNumber = 0
            
            self:_playQueuedAttack(queuedCombo)
        else
            self.isAttackAnimation = false
            self.currentAttackCombo = 0
            self._nextAttackQueued = false
            self._queuedComboNumber = 0
            
            if self.debugMode then
                print("没有排队攻击，返回空闲状态")
            end
            
            if self.combatSystem then
                self.combatSystem:onAttackAnimationComplete()
            end
            
            self:playAnimation("idle", true)
        end
    else
        if self.debugMode then
            print("非攻击动画结束: " .. animationName)
        end
    end
end

-- 处理翻滚动画结束
function ActionSystem:_handleRollAnimationEnd()
    if self.debugMode then
        print("翻滚动画结束")
    end
    
    self._isRolling = false
    self._rollAnimationTimer = 0
    self._rollStartDirection = 1  -- 重置方向
    
    if self.characterMonitor then
        self.characterMonitor:endRoll()
    end
    
    if self._rollQueue then
        self._rollQueue = false
        if self.debugMode then
            print("执行排队的翻滚")
        end
        self:startRoll()
    else
        self:playAnimation("idle", true)
    end
end

-- 播放排队攻击动画
function ActionSystem:_playQueuedAttack(comboNumber)
    if not self.spineNode then return false end
    
    local animKey = self.currentMode .. "_attack_" .. comboNumber
    local spineAnim = self.animationMap[animKey]
    
    if not spineAnim then
        spineAnim = self.currentMode .. "/" .. self.currentMode .. "-a" .. comboNumber
    end
    
    self._animationDuration = self._animationDurations[spineAnim] or 0.8
    
    if self.debugMode then
        print("播放排队攻击动画: " .. spineAnim .. " (combo: " .. comboNumber .. ")")
    end
    
    local success = self.spineNode:play(spineAnim, false)
    
    if success then
        self.isAttackAnimation = true
        self.currentAttackCombo = comboNumber
        self._currentAttackAnimName = spineAnim
        self._attackTimer = 0
        self._animationTimer = 0
        self._inComboWindow = false
        self._comboInputLocked = true
        
        if self.combatSystem then
            self.combatSystem.currentCombo = comboNumber
            self.combatSystem.currentState = "attacking"
            self.combatSystem._comboLocked = false
            self.combatSystem._comboInputQueued = false
            self.combatSystem._queuedComboNumber = 0
            
            if self.debugMode then
                print("通知战斗系统开始第 " .. comboNumber .. " 段攻击")
            end
        end
        
        return true
    else
        print("播放排队攻击动画失败: " .. spineAnim)
        return false
    end
end

-- 更新动作系统
function ActionSystem:update(dt)
    if not self.spineNode or not self._isInitialized then return end
    
    if self._modeSwitchCooldown > 0 then
        self._modeSwitchCooldown = math.max(0, self._modeSwitchCooldown - dt)
    end
    
    if self._rollCooldown > 0 then
        self._rollCooldown = math.max(0, self._rollCooldown - dt)
    end
    
    self:_handleRollInput(dt)
    
    self:_handleModeSwitch(dt)
    
    if not self.isAttackAnimation and not self._isRolling then
        self:_updateMovementAnimation()
    end
    
    if self.isAttackAnimation then
        self._attackTimer = self._attackTimer + dt
        self._animationTimer = self._animationTimer + dt
        
        if not self._inComboWindow and self._attackTimer >= self._comboWindowStart then
            self._inComboWindow = true
            self._comboInputLocked = false
            if self.debugMode then
                print("进入连击窗口 (时间: " .. string.format("%.3f", self._attackTimer) .. "秒)")
            end
        end
        
        if self._inComboWindow and self._attackTimer >= self._comboWindowEnd then
            self._inComboWindow = false
            self._comboInputLocked = true
            if self.debugMode then
                print("离开连击窗口，锁定输入 (时间: " .. string.format("%.3f", self._attackTimer) .. "秒)")
            end
        end
        
        if self._animationTimer >= self._animationDuration then
            if self.debugMode then
                print("动画到时间，模拟AnimationEnd: " .. tostring(self._currentAttackAnimName))
                print("动画计时: " .. string.format("%.3f", self._animationTimer) .. "秒")
                print("预期时长: " .. self._animationDuration .. "秒")
            end
            
            self:onAnimationEnd(self._currentAttackAnimName, self.spineNode)
        end
    end
    
    if self._isRolling then
        self._rollAnimationTimer = self._rollAnimationTimer + dt
        
        if self._rollAnimationTimer >= self._rollAnimationDuration then
            if self.debugMode then
                print("翻滚动画超时，强制结束")
            end
            self:_handleRollAnimationEnd()
        end
    end
end

-- 处理翻滚输入
function ActionSystem:_handleRollInput(dt)
    if not self.movementSystem or not self.movementSystem.keyboardInput then
        return
    end
    
    local keyboardInput = self.movementSystem.keyboardInput
    
    local shiftPressed = keyboardInput:isKeyPressed("Shift") or 
                         keyboardInput:isKeyPressed("LShift") or 
                         keyboardInput:isKeyPressed("RShift")
    local shiftJustPressed = shiftPressed and not self._lastShiftPressed
    
    self._lastShiftPressed = shiftPressed
    
    if shiftJustPressed and self._rollCooldown <= 0 then
        if self.isAttackAnimation or self._isRolling then
            if self.debugMode then
                print("攻击中或翻滚中，排队翻滚")
            end
            self._rollQueue = true
            return
        end
        
        self:startRoll()
    end
end

-- 开始翻滚
function ActionSystem:startRoll()
    if not self.spineNode then
        print("错误：Spine节点为空，无法开始翻滚")
        return false
    end
    
    if self._isRolling then
        if self.debugMode then
            print("已经在翻滚中")
        end
        return false
    end
    
    if self._rollCooldown > 0 then
        if self.debugMode then
            print("翻滚冷却中: " .. string.format("%.3f", self._rollCooldown))
        end
        return false
    end
    
    -- 记录翻滚开始时的方向
    if self.movementSystem then
        local playerEntity = self.movementSystem:getEntity("player")
        if playerEntity then
            self._rollStartDirection = playerEntity.lastDirection or 1
        else
            self._rollStartDirection = 1
        end
    end
    
    if self.characterMonitor and not self.characterMonitor:startRoll() then
        if self.debugMode then
            print("角色监视器不允许开始翻滚")
        end
        return false
    end
    
    local spineAnim = "fangun"
    local success = self.spineNode:play(spineAnim, false)
    
    if success then
        self._isRolling = true
        self._rollAnimationTimer = 0
        self._rollAnimationDuration = self._animationDurations[spineAnim] or 0.4
        self._rollCooldown = self._rollCooldownTime
        
        self.currentAnimation = self.currentMode .. "_roll"
        
        if self.debugMode then
            print("开始翻滚动画: " .. spineAnim .. " (时长: " .. self._rollAnimationDuration .. "秒)")
            print("翻滚方向锁定: " .. self._rollStartDirection)
        end
        return true
    else
        print("播放翻滚动画失败: " .. spineAnim)
        if self.characterMonitor then
            self.characterMonitor:endRoll()
        end
        return false
    end
end

-- 处理模式切换
function ActionSystem:_handleModeSwitch(dt)
    if not self.movementSystem or not self.movementSystem.keyboardInput then
        return
    end
    
    local keyboardInput = self.movementSystem.keyboardInput
    
    local qPressed = keyboardInput:isKeyPressed("Q")
    local qJustPressed = qPressed and not self._lastQPressed
    
    self._lastQPressed = qPressed
    
    if qJustPressed and self._modeSwitchCooldown <= 0 then
        if self.isAttackAnimation or self._isRolling then
            if self.debugMode then
                print("攻击中或翻滚中不能切换模式")
            end
            return
        end
        
        self._modeSwitchCooldown = self._modeSwitchCooldownTime
        
        local currentMode = self.currentMode
        local currentModeInfo = self.characterMonitor:getCurrentMode()
        
        local newMode, newModeInfo = self.characterMonitor:switchMode()
        
        if newMode and newMode ~= currentMode then
            self.currentMode = newMode
            
            local newAnimation = nil
            
            if self.currentAnimation:find("_idle$") then
                newAnimation = newMode .. "_idle"
            elseif self.currentAnimation:find("_walk$") then
                newAnimation = newMode .. "_walk"
            elseif self.currentAnimation:find("_run$") then
                newAnimation = newMode .. "_run"
            elseif self.currentAnimation:find("_jump$") then
                newAnimation = newMode .. "_jump"
            elseif self.currentAnimation:find("_fall$") then
                newAnimation = newMode .. "_fall"
            else
                newAnimation = newMode .. "_idle"
            end
            
            local spineAnim = self.animationMap[newAnimation]
            if spineAnim then
                local success = self.spineNode:play(spineAnim, true)
                if success then
                    self.currentAnimation = newAnimation
                    if self.debugMode then
                        print("模式切换: " .. currentMode .. " -> " .. newMode .. ", 动画: " .. spineAnim)
                    end
                else
                    print("警告：模式切换动画播放失败: " .. spineAnim)
                end
            else
                print("警告：找不到模式切换动画: " .. newAnimation)
            end
        end
    end
end

-- 更新移动动画
function ActionSystem:_updateMovementAnimation()
    if not self.characterMonitor then return end
    
    local unitState = self.characterMonitor:getState()
    if not unitState then return end
    
    local animationType = "idle"
    
    if unitState.moveState == "walking" then
        animationType = "walk"
    elseif unitState.moveState == "running" or unitState.moveState == "sprinting" then
        animationType = "run"
    elseif unitState.jumpState == "jumping" then
        animationType = "jump"
    elseif unitState.jumpState == "falling" then
        animationType = "fall"
    end
    
    if unitState.facingDirection ~= nil then
        if unitState.facingDirection == 1 then
            self.spineNode.fliped = true
        else
            self.spineNode.fliped = false
        end
    end
    
    local animKey = self.currentMode .. "_" .. animationType
    if animKey ~= self.currentAnimation then
        self:playAnimation(animationType, true)
    end
end

-- 播放动画
function ActionSystem:playAnimation(animationType, loop)
    if not self.spineNode then return false end
    
    local animKey = self.currentMode .. "_" .. animationType
    local spineAnim = self.animationMap[animKey]
    
    if not spineAnim then
        spineAnim = self.currentMode .. "/" .. self.currentMode .. "-idle"
    end
    
    local loopParam = loop or false
    
    local shouldPlay = true
    
    if self.spineNode.current == spineAnim and 
       ((self.spineNode.loop and loopParam) or (not self.spineNode.loop and not loopParam)) then
        shouldPlay = false
    end
    
    if shouldPlay then
        local success = self.spineNode:play(spineAnim, loopParam)
        
        if success then
            self.currentAnimation = animKey
            if self.debugMode and not self.isAttackAnimation and not self._isRolling then
                print("播放动画: " .. spineAnim .. " (循环: " .. tostring(loopParam) .. ")")
            end
            return true
        else
            print("播放动画失败: " .. spineAnim)
            return false
        end
    end
    
    return true
end

-- 播放攻击动画
function ActionSystem:playAttackAnimation(mode, comboNumber)
    if not self.spineNode then 
        print("错误：Spine节点为空")
        return false 
    end
    
    local animKey = mode .. "_attack_" .. comboNumber
    local spineAnim = self.animationMap[animKey]
    
    if not spineAnim then
        spineAnim = mode .. "/" .. mode .. "-a" .. comboNumber
    end
    
    self._animationDuration = self._animationDurations[spineAnim] or 0.8
    
    if self.debugMode then
        print("播放攻击动画: " .. spineAnim .. 
              " (combo: " .. comboNumber .. 
              ", 时长: " .. self._animationDuration .. "秒)")
    end
    
    local success = self.spineNode:play(spineAnim, false)
    
    if success then
        self.isAttackAnimation = true
        self.currentAttackCombo = comboNumber
        self._currentAttackAnimName = spineAnim
        self._attackTimer = 0
        self._animationTimer = 0
        self._inComboWindow = false
        self._comboInputLocked = true
        
        if comboNumber == 1 then
            self._nextAttackQueued = false
            self._queuedComboNumber = 0
        end
        
        return true
    else
        print("播放攻击动画失败: " .. spineAnim)
        return false
    end
end

-- 接收连击输入
function ActionSystem:receiveComboInput(comboNumber)
    if not self.isAttackAnimation then
        if self.debugMode then
            print("当前不是攻击状态，忽略连击输入")
        end
        return false
    end
    
    if self._comboInputLocked then
        if self.debugMode then
            print("连击输入被锁定，忽略输入")
        end
        return false
    end
    
    if self._inComboWindow then
        self._nextAttackQueued = true
        self._queuedComboNumber = comboNumber
        self._comboInputLocked = true
        
        if self.debugMode then
            print("✓ 在连击窗口内收到输入，排队第 " .. comboNumber .. " 段攻击")
        end
        return true
    else
        if self.debugMode then
            print("不在连击窗口内，忽略连击输入")
        end
        return false
    end
end

-- 获取动画状态
function ActionSystem:getAnimationState()
    local currentAnim = self.spineNode and self.spineNode.current or "未知"
    local lastCompleted = self.spineNode and self.spineNode.lastCompleted or "无"
    
    return {
        currentAnimation = self.currentAnimation,
        spineCurrentAnimation = currentAnim,
        currentMode = self.currentMode,
        isAttackAnimation = self.isAttackAnimation,
        currentAttackCombo = self.currentAttackCombo,
        inComboWindow = self._inComboWindow,
        comboInputLocked = self._comboInputLocked,
        nextAttackQueued = self._nextAttackQueued,
        queuedComboNumber = self._queuedComboNumber,
        attackTimer = self._attackTimer,
        animationTimer = self._animationTimer,
        animationDuration = self._animationDuration,
        
        isRolling = self._isRolling,
        rollAnimationTimer = self._rollAnimationTimer,
        rollAnimationDuration = self._rollAnimationDuration,
        rollCooldown = self._rollCooldown,
        rollQueue = self._rollQueue,
        rollDirection = self._rollStartDirection,
        
        spineNode = self.spineNode ~= nil,
        lastCompletedAnimation = lastCompleted,
        fliped = self.spineNode and self.spineNode.fliped or false,
        animationSpeed = self.animationSpeed,
        recoveryTime = self.recoveryTime,
        scale = self.scale,
        initialized = self._isInitialized,
        modeSwitchCooldown = self._modeSwitchCooldown
    }
end

-- 清理资源
function ActionSystem:cleanup()
    if self.spineNode and self._animationListenerRegistered then
        self.spineNode["AnimationEnd"] = nil
        self._animationListenerRegistered = false
        if self.debugMode then
            print("清理AnimationEnd事件监听器")
        end
    end
end

return ActionSystem